package com.scwatch.core.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.scwatch.common.orm.Limitable;
import com.scwatch.common.orm.SearchFilter;
import com.scwatch.common.util.Dates;
import com.scwatch.core.domain.CodeDev;
import com.scwatch.core.domain.Invite;
import com.scwatch.core.repository.CodeDevDao;
import com.scwatch.core.repository.InviteDao;
import com.scwatch.core.service.InviteService;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.ServletOutputStream;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Transactional(readOnly = false, isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED)
public class InviteServiceImpl implements InviteService {


    @Override
    public Invite get(Integer id) {
        return inviteDao.findOne(id);
    }

    @Override
    public Page<Invite> findAll(Map<String, String[]> params, Pageable pageable) {
        return inviteDao.findAll(spec(null, params), pageable);
    }

    @Override
    public List<Invite> findAll(Map<String, String[]> params, Limitable limitable) {
        return inviteDao.findAll(spec(null, params), limitable);
    }


    @Override
    public Invite findById(Integer id) {
        return inviteDao.findOne(id);
    }

    @Transactional
    public Invite save(Invite bean) {

        return inviteDao.save(bean);
    }

    @Transactional
    public Invite update(Invite bean) {

        return inviteDao.save(bean);
    }

    @Override
    @Transactional
    public List<Invite> saveList(List<Invite> beans) {
        for(Invite bean:beans){
            inviteDao.save(bean);
        }
        return beans;
    }


    @Override
    @Transactional
    public void delete(Invite bean) {
        inviteDao.delete(bean);
    }

    @Override
    @Transactional
    public Invite[] delete(Integer[] ids) {
        Invite[] beans = new Invite[ids.length];
        for (int i = 0; i < ids.length; i++) {
            Invite invite = findById(ids[i]);
            delete(invite);
            beans[i] = invite;
        }
        return beans;
    }

    public void saveCityInviteCodeQueue(String text) {

        try {
            if(StringUtils.isBlank(text)){
                return;
            }
            JSONObject jsonObject= JSONObject.parseObject(text);
            if(jsonObject==null){
                return;
            }
            Integer siteId=405; //默认直播盐都
            String deviceId=jsonObject.getString("deviceId");
            String inviteCode=jsonObject.getString("inviteCode");

            if(StringUtils.isNotBlank(deviceId) && StringUtils.isNotBlank(inviteCode)){
                //邀请码唯一
                PageRequest pageable=new PageRequest(0,10,new Sort(Sort.Direction.DESC,"id"));
                Map<String, String[]> paramMap =new HashMap<>();
                paramMap.put("EQ_invitationCode", new String[]{inviteCode});
                paramMap.put("EQ_site.id",new String[]{siteId.toString()});
                Page<Invite> pagedList = inviteDao.findAll(spec(null, paramMap), pageable);
                if(pagedList!=null && pagedList.getContent()!=null && pagedList.getContent().size()==1){
                    paramMap =new HashMap<>();
                    paramMap.put("EQ_deviceId", new String[]{deviceId});
                    Page<CodeDev> device_pagedList=codeDevDao.findAll(specCodeDev(null, paramMap), pageable);
                    //当前设备已使用邀请码
                    if(device_pagedList!=null && device_pagedList.getContent()!=null && device_pagedList.getContent().size()>0){
                    }else {
                        Invite invite = pagedList.getContent().get(0);

                        CodeDev codeDev = new CodeDev();
                        codeDev.setDeviceId(deviceId);
                        codeDev.setCodeId(invite);
                        codeDev.setTime(Dates.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss"));
                        codeDevDao.save(codeDev);

                        invite.setDevNum(invite.getCodeDevs().size());
                        inviteDao.save(invite);  //修改设备数量
                    }
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    @Override
    public void export(String[] titles, ServletOutputStream out,List<Invite> inviteList) {
        try{
            // 第一步，创建一个workbook，对应一个Excel文件
            SXSSFWorkbook workbook = new SXSSFWorkbook();
            // 第二步，在webbook中添加一个sheet,对应Excel文件中的sheet
            Sheet hssfSheet = workbook.createSheet("sheet1");
            // 第三步，在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制short
            Row hssfRow = hssfSheet.createRow(0);
            // 第四步，创建单元格，并设置值表头 设置表头居中
            CellStyle hssfCellStyle = workbook.createCellStyle();
            //居中样式
            hssfCellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);

            Cell hssfCell = null;
            for (int i = 0; i < titles.length; i++) {
                hssfCell = hssfRow.createCell(i);//列索引从0开始
                hssfCell.setCellValue(titles[i]);//列名1
                hssfCell.setCellStyle(hssfCellStyle);//列居中显示
            }
            // 第五步，写入实体数据
            for (int i = 0; i < inviteList.size(); i++) {
                hssfRow = hssfSheet.createRow(i+1);
                Invite invite = inviteList.get(i);

                // 第六步，创建单元格，并设置值
                String city="";
                if(invite.getCity()!=null){
                    city=invite.getCity();
                }
                hssfRow.createCell(0).setCellValue(city);


                String code="";
                if(invite.getInvitationCode()!=null){
                    code=invite.getInvitationCode();
                }
                hssfRow.createCell(1).setCellValue(code);

                int devNum=0;
                if(invite.getCodeDevs()!=null){
                      devNum=invite.getCodeDevs().size();
                }
                hssfRow.createCell(2).setCellValue(devNum);
            }
            // 第七步，将文件输出到客户端浏览器
            try {
                workbook.write(out);
                out.flush();
                out.close();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    private Specification<CodeDev> specCodeDev(final Integer codeId, Map<String, String[]> params) {
        Collection<SearchFilter> filters = SearchFilter.parse(params).values();
        final Specification<CodeDev> fsp = SearchFilter.spec(filters, CodeDev.class);
        Specification<CodeDev> sp = new Specification<CodeDev>() {
            public Predicate toPredicate(Root<CodeDev> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate pred = fsp.toPredicate(root, query, cb);
//                if (codeId != null) {
//                    pred = cb.and(pred, cb.equal(root.get("codeId").get("id"), codeId));
//                }
                return pred;
            }
        };
        return sp;
    }

    private Specification<Invite> spec(final Integer codeId, Map<String, String[]> params) {
        Collection<SearchFilter> filters = SearchFilter.parse(params).values();
        final Specification<Invite> fsp = SearchFilter.spec(filters, Invite.class);
        Specification<Invite> sp = new Specification<Invite>() {
            public Predicate toPredicate(Root<Invite> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate pred = fsp.toPredicate(root, query, cb);
//                if (siteId != null) {
//                    pred = cb.and(pred, cb.equal(root.get("codeId").get("id"), codeId));
//                }
                return pred;
            }
        };
        return sp;
    }

    @Autowired
    private InviteDao inviteDao;
    @Autowired
    private CodeDevDao codeDevDao;
}
